<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        class Mypromise {
            constructor(executor) {
                this.inint()
                this.initBind()
                try {
                    executor(this.resolve, this.reject)
                } catch (e) {
                    this.reject(e)
                }
            }
            inint() {
                this.promiseState = 'pendding'
                this.promiseResult = null
                this.onFulfilledCallBacks = []
                this.onRejectedCallBacks = []
            }
            initBind() {
                this.resolve = this.resolve.bind(this)
                this.reject = this.reject.bind(this)
            }
            resolve(value) {
                if (this.promiseState !== 'pendding') return
                this.promiseState = 'fulfilled'
                this.promiseResult = value
                while (this.onFulfilledCallBacks.length) {
                    this.onFulfilledCallBacks.shift()(this.promiseResult)
                }
            }
            reject(reason) {
                if (this.promiseState !== 'pendding') return
                this.promiseState = 'rejected'
                this.promiseResult = reason
                while (this.onRejectedCallBacks.length) {
                    this.onRejectedCallBacks.shift()(this.promiseResult)
                }
            }
            then(onFulfilled, onRejected) {
                onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
                onRejected = typeof onRejected === 'function' ? onRejected : (err) => {
                    throw err
                }
                return new Mypromise((resolve, reject) => {
                    const resolvePromise = (cb) => {
                        setTimeout(() => {
                            const result = cb(this.promiseResult)
                            if (result instanceof Mypromise) {
                                result.then(res => resolve(res), err => reject(err))
                            } else {
                                resolve(result)
                            }
                        })
                    }
                    if (this.promiseState === 'fulfilled') {
                        resolvePromise(onFulfilled)
                    }
                    if (this.promiseState === 'rejected') {
                        resolvePromise(onRejected)
                    }
                    if (this.promiseState === 'pendding') {
                        this.onFulfilledCallBacks.push(resolvePromise.bind(this, onFulfilled))
                        this.onRejectedCallBacks.push(resolvePromise.bind(this, onRejected))
                    }
                })
            }
            static all(promises) {
                const results = []
                let count = 0
                return new Mypromise((resolve, reject) => {
                    const success = (index, res) => {
                        count++
                        results[index] = res
                        if (promises.length === count) resolve(results)
                    }
                    promises.forEach((promise, index) => {
                        if (promise instanceof Mypromise) {
                            promise.then(res => {
                                success(index, res)
                            }, rej => {
                                reject(rej)
                            })
                        } else {
                            success(index, promise)
                        }
                    });
                })
            }
            static race(promise) {
                return new Mypromise((resolve, reject) => {
                    promises.forEach(promise => {
                        if (promise instanceof Mypromise) {
                            promise.then(res => resolve(res), err => reject(err))
                        } else {
                            resolve(promise)
                        }
                    })
                })
            }
            static allSelected(promises) {
                let count = 0
                const results = []
                return new Mypromise((resolve, reject) => {
                    const addData = (index, res) => {
                        results[index] = res
                        count++
                        if (promises.length === count) resolve(results)
                    }
                    promises.forEach((promise, index) => {
                        if (promise instanceof Mypromise) {
                            promise.then(res => {
                                addData(index, res)
                            }, err => {
                                addData(index.err)
                            })
                        } else {
                            addData(index, promise)
                        }
                    })
                })
            }
        }

        const s1 = new Mypromise((resolve, reject) => {
            resolve(10)
        })
        const s2 = new Mypromise((resolve, reject) => {
            resolve(100)
        })
        const s3 = new Mypromise((resolve, reject) => {
            reject('1000')
        })
        Mypromise.allSelected([s1, s2, s3]).then(res => {
            console.log(res);
        })
    </script>
</body>

</html>